#ifndef MPI_OLD_HPP
#define MPI_OLD_HPP

/*
  "Hello World" s využitím MPI
 */
 #include <mpi.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <algorithm>
 #include <sstream>

 #define BUFSIZE 512
 #define TAG 0

#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <limits>

#include "stopwatch.hpp"

bool readFile( const std::string & filename, int * result ){
    std::ifstream f(filename.c_str(),std::ios::in);
    if ( f.is_open() ){
        f >> *result;
        if (f.good() )
            return true;
    }
    return false;
}

class ProcessorsToMachinesLink{

    std::string getProcesorName( int myid, bool full = false ){
        char name[MPI_MAX_PROCESSOR_NAME];
        memset( name, 0, MPI_MAX_PROCESSOR_NAME );
        int len;
        MPI_Get_processor_name( name, &len );
        if ( full ){
            std::ostringstream oss;
            oss  << myid << "@" << name;
            return oss.str();
        }else{
            return std::string( name );
        }
    }

    std::string getHostname( int myid, bool full = false ){
        const size_t size = 150;
        char name[size];
        memset( name, 0, size );
        gethostname( name, size );
        if ( full ){
            std::ostringstream oss;
            oss  << myid << "@" << name;
            return oss.str();
        }else{
            return std::string( name );
        }
    }
    std::string getName( int myid ){
        //return getProcesorName( myid, true );
        return getHostname( myid, false );
    }

    typedef std::map< std::string, std::pair<int,size_t> > map_t;

    size_t usable_mem_size;

    void insert( map_t & map, const std::string & name, size_t mem_size ){
        map_t::iterator i = map.find( name );
        if ( i == map.end() )
            map.insert( std::make_pair( name, std::make_pair( 1, mem_size) ) );
        else{
            ++(i->second.first);
            i->second.second = std::min( i->second.second, mem_size );
        }
    }
    void makeMaster( int numproc ){
        char buff[BUFSIZE];
        MPI_Status stat;

        map_t map;

        //insert( map, getName( 0 ),get_total_system_memory() >> 20 );
        int mem_size;
        for( int i = 1; i < numproc; ++i ){
   //         MPI_Recv( buff, BUFSIZE, MPI_CHAR, i, TAG, MPI_COMM_WORLD, &stat );
            MPI_Recv( &mem_size, 1, MPI_INT, i, TAG, MPI_COMM_WORLD, &stat );
            std::cout << mem_size << std::endl;
   //         std::string s( buff );
  //          insert( map, s, mem_size );
        }

        usable_mem_size = std::numeric_limits<size_t>::max();
        for( map_t::const_iterator i = map.begin(), e = map.end(); i != e; ++i ){
            std::cout << "("<< i->first << ", " << i->second.first  << "x) ... " << i->second.second << " MB" << std::endl;
            usable_mem_size = std::min( usable_mem_size, (i->second.second - 512)/ (size_t)i->second.first );
        }
        std::cout << "usable memory: " << usable_mem_size << " MB" << std::endl;

    }
    void makeSlave( int myid ){
        //std::string s = getName( myid );
        //int mem_size = (get_total_system_memory() >> 20);
        int mem_size = 1;
  //      MPI_Send((void *)s.c_str(), s.length() + 1, MPI_CHAR, 0, TAG, MPI_COMM_WORLD );
//        MPI_Send((void *)"s", 2, MPI_CHAR, 0, TAG, MPI_COMM_WORLD );
        MPI_Send((void *)&mem_size, 1, MPI_INT, 0, TAG, MPI_COMM_WORLD );
    }
public:
    ProcessorsToMachinesLink(){}
    void make( int myid, int numproc ){
        if ( myid == 0 ){
            std::cout << "master" << std::endl;
            makeMaster( numproc );
        }else{
            makeSlave( myid );
        }
    }
};



 int main_old(int argc, char *argv[])
 {

   Stopwatch stopwatch( true );

   int numprocs;
   int myid;



   MPI_Init(&argc,&argv); /* inicializace MPI */
   MPI_Comm_size(MPI_COMM_WORLD,&numprocs); /* zjistíme, kolik procesů běží */
   MPI_Comm_rank(MPI_COMM_WORLD,&myid); /* zjistíme id svého procesu */

   //ProcessorsToMachinesLink link;
   //link.make( myid, numprocs );

   MPI_Finalize();


   if ( myid == 0 ){
       std::cout << "Program took: " << stopwatch.getSeconds() << " s" << std::endl;
       std::cout << "Program took: " << stopwatch.getMiliseconds() << " ms" << std::endl;
   }

   return 0;
 }



#endif // MPI_OLD_HPP
